/**
******************************************************************************
* @file           : studio_proj.h
* @author         : wangyingjie
* @brief          : 经纬度 转 高斯投影，墨卡托投影，地心地固直角坐标系 C 语言版
 *                : 中央经线计算公式： double central = static_cast<int>(lon / 3) * 3;
* @attention      : None
* @date           : 2025/5/12
******************************************************************************
*/

#ifndef STUDIO_PROJ_H
#define STUDIO_PROJ_H

#include "studio_macros.h"
#include "studio_geo_const.h"

#define AO_GAUSS3_NO(lon) static_cast<int>(lon / 3.0 + 1)
#define AO_GAUSS6_NO(lon) static_cast<int>(lon / 6.0 + 1)
#define AO_GAUSS3_L0(no) static_cast<double>(3 * no - 1.5)
#define AO_GAUSS6_L0(no) static_cast<double>(6 * no - 3.0)

class proj
{
  public:
    struct param
    {
        // 中央经度线
        double central{117.0};
        double scale{0.9996};
        double easting{500000.0};  // 东偏移
        // 长半轴
        double major_axis{WGS84::A};
        // 扁率
        double flatten{WGS84::F};
    };

  public:
    /// <summary>
    /// 高斯投影反算经纬度
    /// </summary>
    /// <param name="gx"></param>
    /// <param name="gy"></param>
    /// <param name="lon"></param>
    /// <param name="lat"></param>
    /// <param name="p"></param>
    static void gauss_to_lonlat(const double& gx, const double& gy, double& lon, double& lat, const param& p);

    /// <summary>
    /// 高斯投影反算经纬度,使用静态值速度会更快
    /// </summary>
    /// <param name="gx"></param>
    /// <param name="gy"></param>
    /// <param name="lon"></param>
    /// <param name="lat"></param>
    static void gauss_to_lonlat(const double& central, const double& gx, const double& gy, double& lon, double& lat);

    /// <summary>
    /// 经纬度转高斯投影
    /// </summary>
    /// <param name="lon"></param>
    /// <param name="lat"></param>
    /// <param name="gx"></param>
    /// <param name="gy"></param>
    /// <param name="p"></param>
    static void lonlat_to_gauss(const double& lon, const double& lat, double& gx, double& gy, const param& p);

    /// <summary>
    /// 经纬度转高斯投影,使用静态值速度会更快
    /// </summary>
    /// <param name="lon"></param>
    /// <param name="lat"></param>
    /// <param name="gx"></param>
    /// <param name="gy"></param>
    static void lonlat_to_gauss(const double& central, const double& lon, const double& lat, double& gx, double& gy);

    /// <summary>
    /// 墨卡托转经纬度
    /// </summary>
    /// <param name="mctx"></param>
    /// <param name="mcty"></param>
    /// <param name="lon"></param>
    /// <param name="lat"></param>
    static void mercator_to_lonlat(const double& mctx, const double& mcty, double& lon, double& lat);

    /// <summary>
    /// 经纬度转墨卡托
    /// </summary>
    /// <param name="lon"></param>
    /// <param name="lat"></param>
    /// <param name="mctx"></param>
    /// <param name="mcty"></param>
    static void lonlat_to_mercator(const double& lon, const double& lat, double& mctx, double& mcty);

    /// <summary>
    /// 墨卡托转高斯投影
    /// </summary>
    /// <param name="mctx"></param>
    /// <param name="mcty"></param>
    /// <param name="gx"></param>
    /// <param name="gy"></param>
    /// <param name="p"></param>
    static void mercator_to_gauss(const double& mctx, const double& mcty, double& gx, double& gy, const param& p);

    /// <summary>
    /// 高斯投影转墨卡托
    /// </summary>
    /// <param name="gx"></param>
    /// <param name="gy"></param>
    /// <param name="mctx"></param>
    /// <param name="mcty"></param>
    /// <param name="p"></param>
    static void gauss_to_mercator(const double& gx, const double& gy, double& mctx, double& mcty, const param& p);

    /// <summary>
    /// 墨卡托转高斯投影,使用静态值速度会更快
    /// </summary>
    /// <param name="central"></param>
    /// <param name="mctx"></param>
    /// <param name="mcty"></param>
    /// <param name="gx"></param>
    /// <param name="gy"></param>
    static void mercator_to_gauss(const double& central, const double& mctx, const double& mcty, double& gx, double& gy);

    /// <summary>
    /// 高斯投影转墨卡托,使用静态值速度会更快
    /// </summary>
    /// <param name="central"></param>
    /// <param name="gx"></param>
    /// <param name="gy"></param>
    /// <param name="mctx"></param>
    /// <param name="mcty"></param>
    static void gauss_to_mercator(const double& central, const double& gx, const double& gy, double& mctx, double& mcty);

    /// <summary>
    /// 地心地固直角坐标系 转 经纬坐标系
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <param name="z"></param>
    /// <param name="lon"></param>
    /// <param name="lat"></param>
    /// <param name="height"></param>
    static void ecef_to_lonlat(const double& x, const double& y, const double& z, double& lon, double& lat, double& height);

    /// <summary>
    /// 经纬坐标系 转 地心地固直角坐标系
    /// </summary>
    /// <param name="lon"></param>
    /// <param name="lat"></param>
    /// <param name="height"></param>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <param name="z"></param>
    static void lonlat_to_ecef(const double& lon, const double& lat, const double& height, double& x, double& y, double& z);

  private:
};

#endif  //
